import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../models/folder_model.dart';

/**
 * 文件夹服务
 * 负责文件夹的创建、读取、更新、删除和层级关系管理
 */
class FolderService extends ChangeNotifier {
  static const String _foldersKey = 'folders';
  static const String _folderConfigKey = 'folder_config';
  
  final Map<String, FolderModel> _folders = {};
  FolderSortConfig _sortConfig = const FolderSortConfig();
  bool _isLoading = false;
  String? _error;

  // Getters
  Map<String, FolderModel> get folders => Map.unmodifiable(_folders);
  FolderSortConfig get sortConfig => _sortConfig;
  bool get isLoading => _isLoading;
  String? get error => _error;

  /**
   * 初始化服务，加载本地数据
   */
  Future<void> initialize() async {
    _setLoading(true);
    try {
      await _loadFolders();
      await _loadConfig();
      _clearError();
    } catch (e) {
      _setError('初始化文件夹服务失败: $e');
    } finally {
      _setLoading(false);
    }
  }

  /**
   * 获取根文件夹列表
   */
  List<FolderModel> getRootFolders() {
    final rootFolders = _folders.values
        .where((folder) => folder.isRoot)
        .toList();
    return _sortFolders(rootFolders);
  }

  /**
   * 获取指定父文件夹的子文件夹列表
   */
  List<FolderModel> getChildFolders(String parentId) {
    final parent = _folders[parentId];
    if (parent == null) return [];
    
    final childFolders = parent.childrenIds
        .map((id) => _folders[id])
        .where((folder) => folder != null)
        .cast<FolderModel>()
        .toList();
    
    return _sortFolders(childFolders);
  }

  /**
   * 获取文件夹树结构
   */
  List<FolderTreeNode> getFolderTree() {
    final rootFolders = getRootFolders();
    return rootFolders.map((folder) => _buildTreeNode(folder, null, 0)).toList();
  }

  /**
   * 根据ID获取文件夹
   */
  FolderModel? getFolderById(String id) {
    return _folders[id];
  }

  /**
   * 搜索文件夹
   */
  List<FolderModel> searchFolders(String query) {
    if (query.isEmpty) return [];
    
    final lowerQuery = query.toLowerCase();
    return _folders.values
        .where((folder) => folder.name.toLowerCase().contains(lowerQuery))
        .toList();
  }

  /**
   * 创建新文件夹
   */
  Future<FolderModel> createFolder({
    required String name,
    String? parentId,
    Color? color,
    IconData? icon,
  }) async {
    try {
      // 验证父文件夹存在性
      if (parentId != null && !_folders.containsKey(parentId)) {
        throw Exception('父文件夹不存在');
      }

      // 检查同级文件夹名称重复
      if (_isDuplicateName(name, parentId)) {
        throw Exception('文件夹名称已存在');
      }

      final now = DateTime.now();
      final folder = FolderModel(
        id: _generateId(),
        name: name,
        parentId: parentId,
        createdAt: now,
        updatedAt: now,
        color: color,
        icon: icon,
        sortOrder: _getNextSortOrder(parentId),
      );

      // 添加到文件夹映射
      _folders[folder.id] = folder;

      // 更新父文件夹的子文件夹列表
      if (parentId != null) {
        final parent = _folders[parentId]!;
        final updatedParent = parent.copyWith(
          childrenIds: [...parent.childrenIds, folder.id],
          updatedAt: now,
        );
        _folders[parentId] = updatedParent;
      }

      await _saveFolders();
      notifyListeners();

      return folder;
    } catch (e) {
      _setError('创建文件夹失败: $e');
      rethrow;
    }
  }

  /**
   * 更新文件夹
   */
  Future<FolderModel> updateFolder(
    String id, {
    String? name,
    Color? color,
    IconData? icon,
    bool? isPinned,
    bool? isExpanded,
  }) async {
    try {
      final folder = _folders[id];
      if (folder == null) {
        throw Exception('文件夹不存在');
      }

      // 检查名称重复（如果修改了名称）
      if (name != null && name != folder.name) {
        if (_isDuplicateName(name, folder.parentId, excludeId: id)) {
          throw Exception('文件夹名称已存在');
        }
      }

      final updatedFolder = folder.copyWith(
        name: name,
        color: color,
        icon: icon,
        isPinned: isPinned,
        isExpanded: isExpanded,
        updatedAt: DateTime.now(),
      );

      _folders[id] = updatedFolder;
      await _saveFolders();
      notifyListeners();

      return updatedFolder;
    } catch (e) {
      _setError('更新文件夹失败: $e');
      rethrow;
    }
  }

  /**
   * 移动文件夹
   */
  Future<void> moveFolder(String folderId, String? newParentId, {int? newIndex}) async {
    try {
      final folder = _folders[folderId];
      if (folder == null) {
        throw Exception('文件夹不存在');
      }

      // 验证移动的有效性
      if (!folder.canMoveTo(newParentId, _folders)) {
        throw Exception('无法移动到指定位置');
      }

      // 验证新父文件夹存在性
      if (newParentId != null && !_folders.containsKey(newParentId)) {
        throw Exception('目标父文件夹不存在');
      }

      final oldParentId = folder.parentId;
      final now = DateTime.now();

      // 从原父文件夹移除
      if (oldParentId != null) {
        final oldParent = _folders[oldParentId]!;
        final updatedOldParent = oldParent.copyWith(
          childrenIds: oldParent.childrenIds.where((id) => id != folderId).toList(),
          updatedAt: now,
        );
        _folders[oldParentId] = updatedOldParent;
      }

      // 添加到新父文件夹
      if (newParentId != null) {
        final newParent = _folders[newParentId]!;
        final newChildrenIds = [...newParent.childrenIds];
        
        if (newIndex != null && newIndex >= 0 && newIndex <= newChildrenIds.length) {
          newChildrenIds.insert(newIndex, folderId);
        } else {
          newChildrenIds.add(folderId);
        }
        
        final updatedNewParent = newParent.copyWith(
          childrenIds: newChildrenIds,
          updatedAt: now,
        );
        _folders[newParentId] = updatedNewParent;
      }

      // 更新文件夹的父ID
      final updatedFolder = folder.copyWith(
        parentId: newParentId,
        updatedAt: now,
      );
      _folders[folderId] = updatedFolder;

      await _saveFolders();
      notifyListeners();
    } catch (e) {
      _setError('移动文件夹失败: $e');
      rethrow;
    }
  }

  /**
   * 删除文件夹
   */
  Future<void> deleteFolder(String id, {bool recursive = false}) async {
    try {
      final folder = _folders[id];
      if (folder == null) {
        throw Exception('文件夹不存在');
      }

      // 检查是否有子文件夹
      if (folder.hasChildren && !recursive) {
        throw Exception('文件夹不为空，无法删除');
      }

      final now = DateTime.now();

      // 递归删除子文件夹
      if (recursive) {
        final descendants = folder.getDescendantIds(_folders);
        for (final descendantId in descendants.reversed) {
          _folders.remove(descendantId);
        }
      }

      // 从父文件夹移除
      if (folder.parentId != null) {
        final parent = _folders[folder.parentId]!;
        final updatedParent = parent.copyWith(
          childrenIds: parent.childrenIds.where((childId) => childId != id).toList(),
          updatedAt: now,
        );
        _folders[folder.parentId!] = updatedParent;
      }

      // 删除文件夹
      _folders.remove(id);

      await _saveFolders();
      notifyListeners();
    } catch (e) {
      _setError('删除文件夹失败: $e');
      rethrow;
    }
  }

  /**
   * 重新排序文件夹
   */
  Future<void> reorderFolders(String? parentId, List<String> newOrder) async {
    try {
      if (parentId != null) {
        // 更新父文件夹的子文件夹顺序
        final parent = _folders[parentId];
        if (parent == null) {
          throw Exception('父文件夹不存在');
        }

        final updatedParent = parent.copyWith(
          childrenIds: newOrder,
          updatedAt: DateTime.now(),
        );
        _folders[parentId] = updatedParent;
      }

      // 更新排序顺序
      for (int i = 0; i < newOrder.length; i++) {
        final folderId = newOrder[i];
        final folder = _folders[folderId];
        if (folder != null) {
          _folders[folderId] = folder.copyWith(
            sortOrder: i,
            updatedAt: DateTime.now(),
          );
        }
      }

      await _saveFolders();
      notifyListeners();
    } catch (e) {
      _setError('重新排序失败: $e');
      rethrow;
    }
  }

  /**
   * 更新排序配置
   */
  Future<void> updateSortConfig(FolderSortConfig config) async {
    try {
      _sortConfig = config;
      await _saveConfig();
      notifyListeners();
    } catch (e) {
      _setError('更新排序配置失败: $e');
      rethrow;
    }
  }

  /**
   * 展开/折叠文件夹
   */
  Future<void> toggleFolderExpansion(String id) async {
    try {
      final folder = _folders[id];
      if (folder == null) return;

      final updatedFolder = folder.copyWith(
        isExpanded: !folder.isExpanded,
        updatedAt: DateTime.now(),
      );
      
      _folders[id] = updatedFolder;
      await _saveFolders();
      notifyListeners();
    } catch (e) {
      _setError('切换文件夹展开状态失败: $e');
    }
  }

  // 私有方法

  void _setLoading(bool loading) {
    _isLoading = loading;
    notifyListeners();
  }

  void _setError(String? error) {
    _error = error;
    notifyListeners();
  }

  void _clearError() {
    _error = null;
  }

  String _generateId() {
    return DateTime.now().millisecondsSinceEpoch.toString();
  }

  int _getNextSortOrder(String? parentId) {
    final siblings = parentId == null 
        ? getRootFolders()
        : getChildFolders(parentId);
    
    if (siblings.isEmpty) return 0;
    return siblings.map((f) => f.sortOrder).reduce((a, b) => a > b ? a : b) + 1;
  }

  bool _isDuplicateName(String name, String? parentId, {String? excludeId}) {
    final siblings = parentId == null 
        ? getRootFolders()
        : getChildFolders(parentId);
    
    return siblings.any((folder) => 
        folder.name == name && folder.id != excludeId);
  }

  List<FolderModel> _sortFolders(List<FolderModel> folders) {
    final sorted = [...folders];
    
    // 首先按置顶状态排序
    if (_sortConfig.pinnedFirst) {
      sorted.sort((a, b) {
        if (a.isPinned && !b.isPinned) return -1;
        if (!a.isPinned && b.isPinned) return 1;
        return 0;
      });
    }
    
    // 然后按指定字段排序
    sorted.sort((a, b) {
      int result = 0;
      
      switch (_sortConfig.sortType) {
        case FolderSortType.name:
          result = a.name.compareTo(b.name);
          break;
        case FolderSortType.createdAt:
          result = a.createdAt.compareTo(b.createdAt);
          break;
        case FolderSortType.updatedAt:
          result = a.updatedAt.compareTo(b.updatedAt);
          break;
        case FolderSortType.sortOrder:
          result = a.sortOrder.compareTo(b.sortOrder);
          break;
        case FolderSortType.custom:
          result = a.sortOrder.compareTo(b.sortOrder);
          break;
      }
      
      return _sortConfig.direction == FolderSortDirection.ascending ? result : -result;
    });
    
    return sorted;
  }

  FolderTreeNode _buildTreeNode(FolderModel folder, FolderTreeNode? parent, int level) {
    final children = getChildFolders(folder.id)
        .map((child) => _buildTreeNode(child, null, level + 1))
        .toList();
    
    return FolderTreeNode(
      folder: folder,
      children: children,
      parent: parent,
      level: level,
    );
  }

  Future<void> _loadFolders() async {
    final prefs = await SharedPreferences.getInstance();
    final foldersJson = prefs.getString(_foldersKey);
    
    if (foldersJson != null) {
      final foldersData = jsonDecode(foldersJson) as Map<String, dynamic>;
      _folders.clear();
      
      for (final entry in foldersData.entries) {
        try {
          _folders[entry.key] = FolderModel.fromJson(entry.value);
        } catch (e) {
          debugPrint('加载文件夹失败: ${entry.key}, $e');
        }
      }
    }
  }

  Future<void> _saveFolders() async {
    final prefs = await SharedPreferences.getInstance();
    final foldersData = <String, dynamic>{};
    
    for (final entry in _folders.entries) {
      foldersData[entry.key] = entry.value.toJson();
    }
    
    await prefs.setString(_foldersKey, jsonEncode(foldersData));
  }

  Future<void> _loadConfig() async {
    final prefs = await SharedPreferences.getInstance();
    final configJson = prefs.getString(_folderConfigKey);
    
    if (configJson != null) {
      try {
        final configData = jsonDecode(configJson) as Map<String, dynamic>;
        _sortConfig = FolderSortConfig(
          sortType: FolderSortType.values[configData['sortType'] ?? 0],
          direction: FolderSortDirection.values[configData['direction'] ?? 0],
          pinnedFirst: configData['pinnedFirst'] ?? true,
        );
      } catch (e) {
        debugPrint('加载文件夹配置失败: $e');
      }
    }
  }

  Future<void> _saveConfig() async {
    final prefs = await SharedPreferences.getInstance();
    final configData = {
      'sortType': _sortConfig.sortType.index,
      'direction': _sortConfig.direction.index,
      'pinnedFirst': _sortConfig.pinnedFirst,
    };
    
    await prefs.setString(_folderConfigKey, jsonEncode(configData));
  }
}